
#include "character.h"
#include "area.h"
#include "elf.h"

// ELF 的模型：
// 每个文件只有一个符号表，其中必有四种符号：
//  1、源文件名字。
//  2、各段的名字符号，指向各段的开始。
//  3、符号指向本文件中的某段中的位置。
//  4、符号在本文件外部定义。
// 
// 对应地，也只有一个 string 段。
// string 的管理不由用户管理，在建新段和符号表管理时，
// 会在 string 表中寻找数据，或新建数据。
// 所 string 表管理函数是内部也，用户不可使用的。
// 
//
// 每个文件可以有用户定义的段。
//  1、code 和 data 类型的，这类段在文件中有实际的数据，
//    在运行时在进程地址空间也占有位置。
//    1.1、在本文件的观点，就是它们都有自己的重定位段，指出当本身
//         的内容被移位时，应怎样修改部分相关数据来修正。
//    1.2、它们的重定位段是自动创建的，用户使用时，在管理重定位的
//         函数中使用该段的 sid 来借一步指代该段的重定位段。
//    1.3、只使用有 add 因子的重定位段，具体的重定类型还没有想好。
//    1.4、如果最后发现，重定位段中没有任何数据，则不会产生这个段。
//
//  2、bss 类型的段，这种段只有大小，并不在文件中占用空间，但会在
//     进程的地址空间中占用空间。
//     与上面的两个段不同，该种段不存在重定位段，因为它的数据本身
//     就不存在初始的意义。
//  
//  3、其它类型的段，一些无意义的段，如 note 也可产生，不过不会
//     自动产生相应的重定位段。
//  
// 
#if 0
typedef  struct
{
    tetra  symbol_area;           // 盛装符号表的 area;
    tetra  string_area;           // 盛装串表的 area;
    tetra  section_num;           // 当前文件的 section 数。
    tetra  other;                 // 其它信息。
} ielf_fhdr;


typedef  struct
{
    tetra  name;                  // 指向 string 中的 名字。
    tetra  type;                  // 类型。
    tetra  flags;                 // 标志。
    tetra  size;                  // 当前 section 的尺存，只对 BSS 段有用，因为 area 中有 size 信息。
    tetra  align;                 // 段开始的地址对齐参数。
    tetra  other;                 // 其它信息。
    tetra  self_area;             // 盛装着自己数据的 area, BSS 段的此值为 -1；
    tetra  relocate_area;         // 重定位段的 area 的 id 值。
} ielf_shdr;



// 创建，写，删除。

// 参数 sfname 是源文件名字。
tetra  elf_create_file( tetra * sfname )
{
    tetra  fid;
    ielf_fhdr  tfhdr;
    Elf64_Sym  tsym;
    
    // 为文件的头部和段表建立区块。
    fid = area_create( 1 );
    
    // 存入相应的数据结构。
    tfhdr.symbol_area = area_create( sizeof(Elf64_Sym) );
    tfhdr.string_area = area_create( 1 );
    tfhdr.section_num = 0;
    tfhdr.other = 0;

    /* */
    area_add_data( fid, sizeof(ielf_fhdr), &tfhdr );
    
    // 串表初始化。
    // 加入空串。
    area_add_data( tfhdr.string_area, 1, &(tfhdr.other) );
    
    
    // 符号表初始化。
    // 加入空符号。
    tsym.st_name = 0;
    tsym.st_info = 0;
    tsym.st_other = 0;
    tsym.st_shndx = 0;
    tsym.st_value = 0;
    tsym.st_size = 0;
    
    elf_add_symbol( fid, &tsym );
    
    // 加入源文件名符号。
    tsym.st_name = elf_add_string( fid, sfname );
    tsym.st_info = 0;
    tsym.st_other = 0;
    tsym.st_shndx = 0;
    tsym.st_value = 0;
    tsym.st_size = 0;
    elf_add_symbol( fid, &tsym );
    
    // 返回文件标志符.
    return fid;
    
}


// 将 fid 指向的 ELF 文件数据结构写入到真正的文件中去。
// 文件名字由字符串 fname 指出。
// 非 0 返回指出文件操作错误和其它信息。
// 返回 0 表示成功。
tetra  elf_write_file( tetra fid, tetra * fname )
{
    FILE *  fp;

    /* 需要验证数据的 完整/正确性吗? */
    /* vv */
    
    /* 创建文件 */
    fp = fopen( "temp.o", "wb" );
    if( fp == NULL )
    {
        assert(0);
        return (1);
    }

    /* 写入数据 */
    fwrite();
    return 0;
}

// 删除与这个 ELF 描述符相联的数据结构。
// 无返回值。
void  elf_delete_file( tetra fid )
{
    
}



// 段管理函数。

// 在 ELF 文件中填加一个新段。
// 段的信息在 pshdr 指向的结构中指出。
tetra  elf_create_section( tetra fid, Elf64_Shdr * pshdr )
{
}

// 作用 : : 向段中填加数据。
// ....
tetra  elf_add_data( tetra fid, tetra sid, tetra len, void * buf )
{
}


// ---------- 字符串表管理。------------------------
// 加入字符串。
// 返回这个字符串在串表中是索引值。
tetra  elf_add_string( tetra fid, tetra * str )
{
}

// 在串表中找这个字符串。
// 返回索引值 0 ，表示未找到。
// 返回其它值就是它的索引。

tetra  elf_find_string( tetra fid, tetra * str )
{
}


// ---------------- 符号表管理 --------------------

// 加入一个符号项。
// 符号项的各项属性都由用户赋值。
// 返回值为该符号项在表中的索引。
tetra  elf_add_symbol( tetra fid, Elf64_Sym * psym )
{
}

// 根据 name 域的指针找到一个符号项, 并且返回该符号项的内容。
// 如果没找到返回 0 ；
// 否则返回它在符号表中的索引。
tetra  elf_read_symbol( tetra fid, Elf64_Sym * psym )
{
}

// 修改符号表中的一个符号项。
// 由 sid 确定它的位置。
// 将 psym 指向的内容写入以替换以前的内容。
tetra  elf_write_symbol( tetra fid, tetra symid, Elf64_Sym * psym )
{
}


//
// ------------------- 重定位管理------------------
// 

// 加入定位项，返回索引。
tetra  elf_add_relocate( tetra fid, tetra sid, Elf64_Rel * prel )
{
}

// 寻找定位项。
tetra  elf_read_relocate( tetra fid, tetra sid, tetra rid, Elf64_Rel * prel )
{
}

// 修改定位项。
tetra  elf_write_relocate( tetra fid, tetra sid, tetra rid, Elf64_Rel * prel )
{
}

#endif

